package cn.tinkling.views;

import java.awt.Toolkit;
import java.awt.datatransfer.StringSelection;
import java.text.DecimalFormat;

import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.FocusListener;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.VerifyEvent;
import org.eclipse.swt.events.VerifyListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.part.ViewPart;
import org.eclipse.wb.swt.SWTResourceManager;

import cn.tinkling.Activator;
import cn.tinkling.Constants;
import cn.tinkling.TinklingResourceManager;
import cn.tinkling.preferences.TinklingPreferenceConstants;

public class DPxA extends ViewPart implements Constants {
	/**
	 * The ID of the view as specified by the extension.
	 */
	public static final String ID = "cn.tinkling.views.DPxA";

	private static final int MAX_ALPHA = 0xFF;
	private static final float MAX_ALPHA_F = 1.0f;

	private static final String ERROR = "ERROR";

	boolean pxBroadcast = false;
	boolean dpBroadcast = false;

	boolean alphaBroadcast = false;
	boolean decBroadcast = false;
	boolean hexBroadcast = false;

	DecimalFormat decimalFormat = new DecimalFormat("0.0");
	DecimalFormat decimalFormatAlpha = new DecimalFormat("0.00");

	private Text pxText;
	private Text dpText;
	private Combo dpiCombo;

	private Text textAlpha;
	private Text textDec;
	private Text textHex;

	public DPxA() {
	}

	@Override
	public void createPartControl(Composite parent) {
		GridLayout gl_parent = new GridLayout(1, false);
		gl_parent.marginHeight = 10;
		gl_parent.marginWidth = 10;
		gl_parent.verticalSpacing = 10;
		gl_parent.horizontalSpacing = 10;
		parent.setLayout(gl_parent);
		parent.setBackground(TinklingResourceManager.getDefaultBackground());

		onPx2DipGroupCreate(parent);
		onAlphaGroupCreate(parent);
	}

	private void onPx2DipGroupCreate(Composite parent) {
		Group pxToDipGroup = new Group(parent, SWT.NONE);
		pxToDipGroup.setBackground(TinklingResourceManager.getDefaultBackground());
		GridLayout gl_pxToDipGroup = new GridLayout(3, false);
		gl_pxToDipGroup.horizontalSpacing = 10;
		gl_pxToDipGroup.verticalSpacing = 10;
		gl_pxToDipGroup.marginWidth = 15;
		gl_pxToDipGroup.marginHeight = 15;
		pxToDipGroup.setLayout(gl_pxToDipGroup);
		pxToDipGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
		pxToDipGroup.setFont(SWTResourceManager.getFont("Microsoft YaHei UI Light", 14, SWT.ITALIC));
		pxToDipGroup.setText("Px to Dip");

		Composite pxComposite = new Composite(pxToDipGroup, SWT.BORDER);
		pxComposite.setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
		GridLayout pxComGridLayout = new GridLayout(2, false);
		pxComGridLayout.marginWidth = 20;
		pxComposite.setLayout(pxComGridLayout);
		GridData pxComGD = new GridData(SWT.FILL, SWT.CENTER, true, true, 1, 1);
		pxComGD.heightHint = 100;
		pxComposite.setLayoutData(pxComGD);

		pxText = new Text(pxComposite, SWT.RIGHT);
		pxText.setForeground(SWTResourceManager.getColor(40, 40, 34));
		pxText.setText("0");
		pxText.setFont(SWTResourceManager.getFont("Microsoft YaHei UI Light", 38, SWT.NORMAL));
		pxText.setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
		pxText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, true, 1, 1));

		Label pxLabel = new Label(pxComposite, SWT.WRAP | SWT.CENTER);
		pxLabel.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, true, 1, 1));
		pxLabel.setFont(SWTResourceManager.getFont("Microsoft YaHei UI Light", 30, SWT.BOLD));
		pxLabel.setForeground(SWTResourceManager.getColor(139, 139, 159));
		pxLabel.setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
		pxLabel.setText("Px");

		dpiCombo = new Combo(pxToDipGroup, SWT.READ_ONLY);
		dpiCombo.setForeground(SWTResourceManager.getColor(SWT.COLOR_WIDGET_BORDER));
		dpiCombo.setFont(SWTResourceManager.getFont("Microsoft YaHei UI Light", 20, SWT.ITALIC));
		dpiCombo.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false, 1, 1));
		dpiCombo.setItems(DPIS);

		IPreferenceStore store = Activator.getDefault().getPreferenceStore();
		int select = store.getInt(TinklingPreferenceConstants.P_DPI);
		dpiCombo.select(select);

		Composite dpComposite = new Composite(pxToDipGroup, SWT.BORDER);
		dpComposite.setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
		GridLayout dpComGridLayout = new GridLayout(2, false);
		dpComGridLayout.marginWidth = 20;
		dpComposite.setLayout(dpComGridLayout);
		GridData dpComGD = new GridData(SWT.FILL, SWT.CENTER, true, true, 1, 1);
		dpComGD.heightHint = 100;
		dpComposite.setLayoutData(dpComGD);

		dpText = new Text(dpComposite, SWT.RIGHT);
		dpText.setForeground(SWTResourceManager.getColor(40, 40, 34));
		dpText.setText("0");
		dpText.setFont(SWTResourceManager.getFont("Microsoft YaHei UI Light", 38, SWT.NORMAL));
		dpText.setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
		dpText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, true, 1, 1));

		Label dpLabel = new Label(dpComposite, SWT.WRAP | SWT.CENTER);
		dpLabel.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, true, 1, 1));
		dpLabel.setFont(SWTResourceManager.getFont("Microsoft YaHei UI Light", 30, SWT.BOLD));
		dpLabel.setForeground(SWTResourceManager.getColor(139, 139, 159));
		dpLabel.setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
		dpLabel.setText("Dp");

		createMenu(pxText, false);
		createMenu(dpText, true);

		addListeners(pxText);
		addListeners(dpText);

		initModifyListener();
	}

	private void initModifyListener() {
		dpiCombo.addModifyListener(new ModifyListener() {

			@Override
			public void modifyText(ModifyEvent e) {
				String str = pxText.getText();
				pxText.setText(str);
			}
		});
		pxText.addModifyListener(new ModifyListener() {

			@Override
			public void modifyText(ModifyEvent e) {
				if (pxBroadcast) {
					pxBroadcast = false;
					return;
				}

				float px = 0f;
				try {
					String str = pxText.getText();
					px = Float.parseFloat(str);
				} catch (Exception ex) {
					pxBroadcast = true;
					if (pxText.getText().length() == 0) {
						pxText.setText("0");
						pxText.setSelection(0, pxText.getText().length());
					} else {
						pxText.setText(ERROR);
					}
				}

				int index = dpiCombo.getSelectionIndex();
				double dip = px / DENSITYS[index];

				dpBroadcast = true;
				dpText.setText(getNumberString(dip));
			}
		});
		dpText.addModifyListener(new ModifyListener() {

			@Override
			public void modifyText(ModifyEvent e) {
				if (dpBroadcast) {
					dpBroadcast = false;
					return;
				}

				float dp = 0f;
				try {
					String str = dpText.getText();
					dp = Float.parseFloat(str);
				} catch (Exception ex) {
					dpBroadcast = true;
					if (dpText.getText().length() == 0) {
						dpText.setText("0");
						dpText.setSelection(0, pxText.getText().length());
					} else {
						dpText.setText(ERROR);
					}
				}

				int index = dpiCombo.getSelectionIndex();
				double px = dp * DENSITYS[index];

				pxBroadcast = true;
				pxText.setText(getNumberString(px));
			}
		});
	}

	public String getNumberString(double number) {
		String result = decimalFormat.format(number);
		if (result.endsWith(".0")) {
			result = result.substring(0, result.length() - 2);
		}

		return result;
	}

	private void addListeners(final Text text) {
		text.addFocusListener(new FocusListener() {

			@Override
			public void focusLost(FocusEvent e) {
			}

			@Override
			public void focusGained(FocusEvent e) {
				if (ERROR.equals(text.getText())) {
					text.setText("0");
				}

				text.setSelection(0, text.getText().length());
			}
		});

		setInputFetter(text, new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.', SWT.BS, SWT.DEL, SWT.LEFT, (char) SWT.RIGHT });
	}

	private void setInputFetter(final Text text, final char[] chars) {
		text.addKeyListener(new KeyListener() {

			@Override
			public void keyReleased(KeyEvent e) {
			}

			@Override
			public void keyPressed(KeyEvent e) {
				boolean doit = false;
				for (char c : chars) {
					doit |= c == e.character;

					if (doit)
						break;
				}

				e.doit = doit;
			}
		});
	}

	private void createMenu(final Text text, final boolean withDp) {
		Menu menu = new Menu(text);
		text.setMenu(menu);

		MenuItem menuItemClear = new MenuItem(menu, SWT.NONE);
		menuItemClear.setText("Clear");
		menuItemClear.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				text.setText("0");
				text.setSelection(0, text.getText().length());
			}
		});

		MenuItem menuItemCopy = new MenuItem(menu, SWT.NONE);
		menuItemCopy.setText("Copy");
		menuItemCopy.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				if (text.getText().length() > 0 && !ERROR.equals(text.getText())) {
					String str = text.getText();

					try {
						str = getNumberString(Double.parseDouble(str));
					} catch (Exception ex) {
						ex.printStackTrace();
						return;
					}

					if (withDp) {
						str += "dp";
					}
					StringSelection stsel = new StringSelection(str);
					Toolkit.getDefaultToolkit().getSystemClipboard().setContents(stsel, stsel);
				}
			}
		});

		MenuItem menuItemPaste = new MenuItem(menu, SWT.NONE);
		menuItemPaste.setText("Paste");
		menuItemPaste.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				text.paste();
			}
		});
	}

	private void onAlphaGroupCreate(Composite parent) {
		Group grpAlpha = new Group(parent, SWT.SHADOW_OUT);
		grpAlpha.setBackground(TinklingResourceManager.getDefaultBackground());
		GridLayout gl_pxToDipGroup = new GridLayout(6, false);
		gl_pxToDipGroup.horizontalSpacing = 10;
		gl_pxToDipGroup.verticalSpacing = 10;
		gl_pxToDipGroup.marginWidth = 15;
		gl_pxToDipGroup.marginHeight = 15;
		grpAlpha.setLayout(gl_pxToDipGroup);
		grpAlpha.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
		grpAlpha.setFont(SWTResourceManager.getFont("Microsoft YaHei UI Light", 14, SWT.ITALIC));
		grpAlpha.setText("Alpha");

		onCreateAlphaEditText(grpAlpha);
		onCreateDecEditText(grpAlpha);
		onCreateHexEditText(grpAlpha);
	}

	private void onCreateAlphaEditText(Group grpAlpha) {
		Label labelAlpha = new Label(grpAlpha, SWT.NONE);
		labelAlpha.setForeground(SWTResourceManager.getColor(74, 60, 62));
		labelAlpha.setFont(SWTResourceManager.getFont("Microsoft YaHei UI Light", 14, SWT.NORMAL));
		labelAlpha.setBackground(TinklingResourceManager.getDefaultBackground());
		labelAlpha.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, true, 1, 1));
		labelAlpha.setText("Alpha(0~1):");

		Composite alphaComposite = new Composite(grpAlpha, SWT.BORDER);
		alphaComposite.setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
		GridLayout alphaGridLayout = new GridLayout(1, false);
		alphaGridLayout.marginWidth = 3;
		alphaGridLayout.verticalSpacing = 2;
		alphaGridLayout.horizontalSpacing = 2;
		alphaGridLayout.marginHeight = 2;
		alphaComposite.setLayout(alphaGridLayout);
		GridData alphaComGD = new GridData(SWT.FILL, SWT.CENTER, true, true, 1, 1);
		alphaComGD.heightHint = 100;
		alphaComposite.setLayoutData(alphaComGD);

		textAlpha = new Text(alphaComposite, SWT.CENTER);
		textAlpha.setTextLimit(5);
		textAlpha.setForeground(SWTResourceManager.getColor(40, 40, 34));
		textAlpha.setText("1");
		textAlpha.setFont(SWTResourceManager.getFont("Microsoft YaHei UI Light", 38, SWT.NORMAL));
		textAlpha.setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
		textAlpha.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, true, 1, 1));

		setInputFetter(textAlpha, new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.', SWT.BS, SWT.DEL, SWT.LEFT, (char) SWT.RIGHT });

		textAlpha.addModifyListener(new ModifyListener() {

			@Override
			public void modifyText(ModifyEvent e) {
				if (alphaBroadcast) {
					alphaBroadcast = false;
					return;
				}

				float alpha = MAX_ALPHA_F;
				try {
					alpha = Float.parseFloat(textAlpha.getText());

					if (alpha > MAX_ALPHA_F) {
						alpha = MAX_ALPHA_F;
						throw new Exception();
					}
				} catch (Exception ex) {
					if (textAlpha.getText().length() > 0) {
						alphaBroadcast = true;
						textAlpha.setText("1");
						textAlpha.setSelection(0, textAlpha.getText().length());
					}
				}

				int alphaInt = (int) (MAX_ALPHA * alpha + 0.5f);

				decBroadcast = true;
				textDec.setText(String.valueOf(alphaInt));

				hexBroadcast = true;
				textHex.setText(Integer.toHexString(alphaInt));
			}
		});
	}

	private void onCreateDecEditText(Group grpAlpha) {
		Label labelDec = new Label(grpAlpha, SWT.NONE);
		labelDec.setForeground(SWTResourceManager.getColor(74, 60, 62));
		labelDec.setFont(SWTResourceManager.getFont("Microsoft YaHei UI Light", 14, SWT.NORMAL));
		labelDec.setBackground(TinklingResourceManager.getDefaultBackground());
		GridData gd_labelDec = new GridData(SWT.RIGHT, SWT.CENTER, false, true, 1, 1);
		gd_labelDec.horizontalIndent = 10;
		labelDec.setLayoutData(gd_labelDec);
		labelDec.setText("Dec:");

		Composite decComposite = new Composite(grpAlpha, SWT.BORDER);
		decComposite.setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
		GridLayout decGridLayout = new GridLayout(1, false);
		decGridLayout.marginWidth = 3;
		decGridLayout.verticalSpacing = 2;
		decGridLayout.horizontalSpacing = 2;
		decGridLayout.marginHeight = 2;
		decComposite.setLayout(decGridLayout);
		GridData decComGD = new GridData(SWT.FILL, SWT.CENTER, true, true, 1, 1);
		decComGD.heightHint = 100;
		decComposite.setLayoutData(decComGD);

		textDec = new Text(decComposite, SWT.CENTER);
		textDec.setTextLimit(3);
		textDec.setForeground(SWTResourceManager.getColor(40, 40, 34));
		textDec.setText("255");
		textDec.setFont(SWTResourceManager.getFont("Microsoft YaHei UI Light", 38, SWT.NORMAL));
		textDec.setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
		textDec.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, true, 1, 1));

		setInputFetter(textDec, new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', SWT.BS, SWT.DEL, SWT.LEFT, (char) SWT.RIGHT });

		textDec.addModifyListener(new ModifyListener() {

			@Override
			public void modifyText(ModifyEvent e) {
				if (decBroadcast) {
					decBroadcast = false;
					return;
				}

				int alpha = MAX_ALPHA;
				try {
					alpha = Integer.parseInt(textDec.getText());

					if (alpha > MAX_ALPHA) {
						alpha = MAX_ALPHA;
						throw new Exception();
					}
				} catch (Exception ex) {
					if (textDec.getText().length() > 0) {
						decBroadcast = true;
						textDec.setText(String.valueOf(alpha));
						textDec.setSelection(0, textDec.getText().length());
					}
				}

				double alphaD = alpha / (double) MAX_ALPHA;

				alphaBroadcast = true;
				textAlpha.setText(decimalFormatAlpha.format(alphaD));

				hexBroadcast = true;
				textHex.setText(Integer.toHexString(alpha));
			}
		});
	}

	private void onCreateHexEditText(Group grpAlpha) {
		Label labelHex = new Label(grpAlpha, SWT.NONE);
		labelHex.setForeground(SWTResourceManager.getColor(74, 60, 62));
		labelHex.setFont(SWTResourceManager.getFont("Microsoft YaHei UI Light", 14, SWT.NORMAL));
		labelHex.setBackground(TinklingResourceManager.getDefaultBackground());
		GridData gd_labelHex = new GridData(SWT.RIGHT, SWT.CENTER, false, true, 1, 1);
		gd_labelHex.horizontalIndent = 10;
		labelHex.setLayoutData(gd_labelHex);
		labelHex.setText("Hex:");

		Composite hexComposite = new Composite(grpAlpha, SWT.BORDER);
		hexComposite.setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
		GridLayout hexGridLayout = new GridLayout(1, false);
		hexGridLayout.marginWidth = 3;
		hexGridLayout.verticalSpacing = 2;
		hexGridLayout.horizontalSpacing = 2;
		hexGridLayout.marginHeight = 2;
		hexComposite.setLayout(hexGridLayout);
		GridData hexComGD = new GridData(SWT.FILL, SWT.CENTER, true, true, 1, 1);
		hexComGD.heightHint = 100;
		hexComposite.setLayoutData(hexComGD);

		textHex = new Text(hexComposite, SWT.CENTER);
		textHex.setTextLimit(2);
		textHex.setForeground(SWTResourceManager.getColor(40, 40, 34));
		textHex.setText("FF");
		textHex.setFont(SWTResourceManager.getFont("Microsoft YaHei UI Light", 38, SWT.NORMAL));
		textHex.setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
		textHex.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, true, 1, 1));

		setInputFetter(textHex, new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'a', 'b', 'c', 'd', 'e',
				'f', SWT.BS, SWT.DEL, SWT.LEFT, (char) SWT.RIGHT });
		textHex.addVerifyListener(new VerifyListener() {

			@Override
			public void verifyText(VerifyEvent e) {
				e.text = e.text.toUpperCase();
			}
		});

		textHex.addModifyListener(new ModifyListener() {

			@Override
			public void modifyText(ModifyEvent e) {
				if (hexBroadcast) {
					hexBroadcast = false;
					return;
				}

				int alpha = MAX_ALPHA;
				try {
					alpha = Integer.parseInt(textHex.getText(), 16);

					if (alpha > MAX_ALPHA) {
						alpha = MAX_ALPHA;
						throw new Exception();
					}
				} catch (Exception ex) {
					if (textHex.getText().length() > 0) {
						hexBroadcast = true;
						textHex.setText(Integer.toHexString(alpha));
						textHex.setSelection(0, textHex.getText().length());
					}
				}

				double alphaD = alpha / (double) MAX_ALPHA;

				alphaBroadcast = true;
				textAlpha.setText(decimalFormatAlpha.format(alphaD));

				decBroadcast = true;
				textDec.setText(String.valueOf(alpha));
			}
		});
	}

	@Override
	public void setFocus() {
		pxText.setFocus();
	}
}
